using System;
using System.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.Rendering;

namespace UnityX
{
    public partial class RecorderVideo
    {
        public enum VideoInputType
        {
            Unknown,
            Screen,
            ScreenWithoutUI,
            Camera,
            WebCam,
        }
        internal class RecorderVideoVideoUpdate : MonoBehaviour
        {
            private void OnPostRender()
            {
            }
        }

        //
        private Camera camera = null;
        private WebCamTexture webCamTexture = null;

        private RecorderVideoVideoUpdate videoMonoBehaviour = null;
        private Texture2D texture2D = null;

        private VideoInputType videoInputType = VideoInputType.Unknown;

        public void SetVideoInputByScreen(float frameRate = 60, int videoBitRate = 10_000_000)
        {
            if (videoInputType != VideoInputType.Unknown)
            {
                throw new InvalidOperationException("VideoInput已经设置！");
            }
            this.x = 0;
            this.y = 0;
            this.width = Screen.width;
            this.height = Screen.height;
            this.frameRate = frameRate;
            this.videoBitRate = videoBitRate;
            this.videoInputType = VideoInputType.Screen;
        }
        public void SetVideoInputByScreen(int x, int y, int width, int height, float frameRate = 60, int videoBitRate = 10_000_000)
        {
            if (videoInputType != VideoInputType.Unknown)
            {
                throw new InvalidOperationException("VideoInput已经设置！");
            }
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.frameRate = frameRate;
            this.videoBitRate = videoBitRate;
            this.videoInputType = VideoInputType.Screen;
        }
        public void SetVideoInputByScreenWithoutUI(float frameRate = 60, int videoBitRate = 10_000_000)
        {
            if (videoInputType != VideoInputType.Unknown)
            {
                throw new InvalidOperationException("VideoInput已经设置！");
            }
            if (RenderPipelineManager.currentPipeline == null)
            {
                throw new InvalidOperationException("ScreenWithoutUI录制模式只支持URP或HDRP渲染管线！");
            }
            this.x = 0;
            this.y = 0;
            this.width = Screen.width;
            this.height = Screen.height;
            this.frameRate = frameRate;
            this.videoBitRate = videoBitRate;
            this.videoInputType = VideoInputType.ScreenWithoutUI;
        }
        public void SetVideoInputByScreenWithoutUI(int x, int y, int width, int height, float frameRate = 60, int videoBitRate = 10_000_000)
        {
            if (videoInputType != VideoInputType.Unknown)
            {
                throw new InvalidOperationException("VideoInput已经设置！");
            }
            if (RenderPipelineManager.currentPipeline == null)
            {
                throw new InvalidOperationException("ScreenWithoutUI录制模式只支持URP或HDRP渲染管线！");
            }
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.frameRate = frameRate;
            this.videoBitRate = videoBitRate;
            this.videoInputType = VideoInputType.ScreenWithoutUI;
        }
        public void SetVideoInputByCamera(Camera camera, float frameRate = 60, int videoBitRate = 10_000_000)
        {
            throw new InvalidOperationException("Camera类型未实现！");
        }
        public void SetVideoInputByCamera(Camera camera, int x, int y, int width, int height, float frameRate = 60, int videoBitRate = 10_000_000)
        {
            throw new InvalidOperationException("Camera类型未实现！");
        }
        public void SetVideoInputByWebCam(WebCamTexture webCamTexture, float frameRate = 60, int videoBitRate = 10_000_000)
        {
            if (videoInputType != VideoInputType.Unknown)
            {
                throw new InvalidOperationException("VideoInput已经设置！");
            }
            if (!webCamTexture.isPlaying)
            {
                throw new InvalidOperationException("WebCamTexture必须处于播放模式下！请确认已经调用webCamTexture.Play()并且成功！");
                //webCamTexture.Play();
            }
            this.width = webCamTexture.width;
            this.height = webCamTexture.height;
            this.frameRate = frameRate;
            this.videoBitRate = videoBitRate;
            this.webCamTexture = webCamTexture;
            this.videoInputType = VideoInputType.WebCam;
        }

        private unsafe void CommitFrame()
        {
            duration = nowTime - beginTime;
            RecorderVideoNativeAPI.CommitFrame(recorder, texture2D.GetRawTextureData<byte>().GetUnsafeReadOnlyPtr(), duration);
        }
        private IEnumerator CommitScreen()
        {
            while (true)
            {
                yield return new WaitForEndOfFrame();
                texture2D.ReadPixels(new Rect(x, y, width, height), 0, 0, false);
                CommitFrame();
            }
        }
        private void CommitScreenWithoutUI(ScriptableRenderContext context, Camera[] arg2)
        {
            texture2D.ReadPixels(new Rect(x, y, width, height), 0, 0, false);
            CommitFrame();
        }
        private void CommitCamera(ScriptableRenderContext context, Camera camera)
        {
            if (camera == this.camera)
            {
                texture2D.ReadPixels(new Rect(x, y, width, height), 0, 0, false);
                CommitFrame();
            }
        }
        private IEnumerator CommitWebCam()
        {
            while (true)
            {
                yield return new WaitForEndOfFrame();
                Graphics.CopyTexture(webCamTexture, texture2D);
                CommitFrame();
            }
        }

        private void CreateVideoCommit()
        {
            texture2D = new Texture2D(width, height, TextureFormat.RGBA32, false, false);
            switch (videoInputType)
            {
                case VideoInputType.Unknown:
                    throw new InvalidOperationException("未设置视频输入！请调用SetVideoInput函数设置一个视频输入类型！");
                case VideoInputType.Screen:
                    {
                        videoMonoBehaviour = gameObject.AddComponent<RecorderVideoVideoUpdate>();
                        videoMonoBehaviour.StartCoroutine(CommitScreen());
                    }
                    break;
                case VideoInputType.ScreenWithoutUI:
                    {
                        RenderPipelineManager.endFrameRendering += CommitScreenWithoutUI;
                    }
                    break;
                case VideoInputType.Camera:
                    {
                        RenderPipelineManager.endCameraRendering += CommitCamera;
                    }
                    break;
                case VideoInputType.WebCam:
                    {
                        videoMonoBehaviour = gameObject.AddComponent<RecorderVideoVideoUpdate>();
                        videoMonoBehaviour.StartCoroutine(CommitWebCam());
                    }
                    break;
                default:
                    break;
            }
        }
        private void DestroyVideoCommit()
        {
            switch (videoInputType)
            {
                case VideoInputType.Unknown:
                    break;
                case VideoInputType.Screen:
                    break;
                case VideoInputType.ScreenWithoutUI:
                    RenderPipelineManager.endFrameRendering -= CommitScreenWithoutUI;
                    break;
                case VideoInputType.Camera:
                    RenderPipelineManager.endCameraRendering -= CommitCamera;
                    break;
                case VideoInputType.WebCam:
                    break;
                default:
                    break;
            }
            if (videoMonoBehaviour != null)
            {
                videoMonoBehaviour.StopAllCoroutines();
                UnityEngine.Object.Destroy(audioMonoBehaviour);
                videoMonoBehaviour = null;
            }
            if (texture2D != null)
            {
                UnityEngine.Object.Destroy(texture2D);
                texture2D = null;
            }
            camera = null;
            webCamTexture = null;
        }
    }
}